package com.qinsilk.axon.inventory

import com.qinsilk.axon.inventory.command.*
import com.qinsilk.axon.inventory.query.InventoryQueryModel
import com.qinsilk.axon.inventory.query.InventoryRepository
import java.util.*
import java.util.concurrent.CompletableFuture
import org.axonframework.commandhandling.gateway.CommandGateway
import org.springframework.web.bind.annotation.*

@RestController
@RequestMapping("/inventory")
class InventoryController(
        private val commandGateway: CommandGateway,
        private val inventoryRepository: InventoryRepository
) {

    @PostMapping("/create")
    fun createInventory(@RequestBody request: CreateInventoryRequest): CompletableFuture<String> {
        val inventoryId = UUID.randomUUID().toString()
        requireNotNull(request.productName)
        requireNotNull(request.initialQuantity)
        return commandGateway.send<String>(
                CreateInventoryCommand(inventoryId, request.productName!!, request.initialQuantity)
        )
    }

    @PostMapping("/{inventoryId}/stock-in")
    fun stockIn(
            @PathVariable inventoryId: String,
            @RequestBody request: StockOperationRequest
    ): CompletableFuture<String> {
        requireNotNull(request.reason)
        return commandGateway.send<String>(
                StockInCommand(inventoryId, request.quantity, request.reason)
        )
    }

    @PostMapping("/{inventoryId}/stock-out")
    fun stockOut(
            @PathVariable inventoryId: String,
            @RequestBody request: StockOperationRequest
    ): CompletableFuture<String> {
        return commandGateway.send<String>(
                StockOutCommand(inventoryId, request.quantity, request.reason)
        )
    }

    @PostMapping("/{inventoryId}/cancel")
    fun cancelOperation(
            @PathVariable inventoryId: String,
            @RequestBody request: CancelOperationRequest
    ): CompletableFuture<String> {
        return commandGateway.send<String>(CancelOperationCommand(inventoryId, request.eventId))
    }

    @GetMapping
    fun getAllInventories(): List<InventoryQueryModel> {
        return inventoryRepository.findAll()
    }

    @GetMapping("/{inventoryId}")
    fun getInventory(@PathVariable inventoryId: String): InventoryQueryModel? {
        return inventoryRepository.findById(inventoryId).orElse(null)
    }

    // 请求体类
    data class CreateInventoryRequest(
            var productName: String? = null,
            var initialQuantity: Int = 0
    )

    data class StockOperationRequest(var quantity: Int = 0, var reason: String){
        constructor():this(0, "")
    }

    data class CancelOperationRequest(var eventId: String = UUID.randomUUID().toString())
}
